/**
 * 专门用于获取 GitHub 项目 package.json 的工具函数
 * 支持多个镜像源，自动降级重试
 */
export class GithubPackageFetcher {
  // 可用的镜像源列表（按优先级排序）
  static MIRROR_SOURCES = [
    {
      name: 'GitHub原生',
      url: (owner, repo, ref) => `https://raw.githubusercontent.com/${owner}/${repo}/${ref}/package.json`
    },
    {
      name: 'jsDelivr',
      url: (owner, repo, ref) => `https://cdn.jsdelivr.net/gh/${owner}/${repo}@${ref}/package.json`
    },
    {
      name: 'FastGit',
      url: (owner, repo, ref) => `https://raw.fastgit.org/${owner}/${repo}/${ref}/package.json`
    },
    {
      name: 'GitHub Mirror',
      url: (owner, repo, ref) => `https://ghproxy.com/https://raw.githubusercontent.com/${owner}/${repo}/${ref}/package.json`
    }

  ];

  // 主方法：获取 package.json
  static async getPackageJson(githubUrl) {
    const { owner, repo, ref } = await this.parseUrl(githubUrl);

    // 尝试所有镜像源
    for (const source of this.MIRROR_SOURCES) {
      try {
        const rawUrl = source.url(owner, repo, ref);
        console.log(`尝试从 ${source.name} 获取: ${rawUrl}`);

        const response = await this.fetchWithTimeout(rawUrl, 8000);
        if (response.ok) {
          console.log(`✅ 成功从 ${source.name} 获取 package.json`);
          return await response.json();
        }
      } catch (error) {
        console.warn(`❌ ${source.name} 失败:`, error.message);
        // 继续尝试下一个源
        continue;
      }
    }

    throw new Error(`所有镜像源都失败了，无法获取 ${owner}/${repo} 的 package.json`);
  }

  // 带超时的 fetch
  static async fetchWithTimeout(url, timeout = 8000) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), timeout);

    try {
      const response = await fetch(url, {
        signal: controller.signal,
        headers: {
          'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
        }
      });
      clearTimeout(timeoutId);
      return response;
    } catch (error) {
      clearTimeout(timeoutId);
      throw error;
    }
  }

  // 解析 URL 并确定分支引用
  static async parseUrl(url) {
    const parsed = new URL(url);
    const parts = parsed.pathname.split("/").filter(Boolean);

    if (parts.length < 2) throw new Error("Invalid GitHub URL");
    console.log('parts', parts);

    const owner = parts[0];
    const repo = parts[1];
    let ref = null;

    // 处理有指定分支/标签的情况
    if (parts.length > 3 && (parts[2] === "tree" || parts[2] === "blob")) {
      ref = parts[3];
    }

    // 如果没有指定分支，获取默认分支
    if (!ref) {
      ref = await this.getDefaultBranch(owner, repo);
    }

    return { owner, repo, ref };
  }

  // 获取默认分支（也添加重试机制）
  static async getDefaultBranch(owner, repo) {
    const githubApiUrls = [
      `https://api.github.com/repos/${owner}/${repo}`,
      `https://ghproxy.com/https://api.github.com/repos/${owner}/${repo}`
    ];

    for (const apiUrl of githubApiUrls) {
      try {
        console.log(`尝试获取默认分支: ${apiUrl}`);
        const response = await this.fetchWithTimeout(apiUrl, 5000);
        if (response.ok) {
          const data = await response.json();
          console.log('分支', data.default_branch);
          return data.default_branch || "main";
        }
      } catch (error) {
        console.warn(`GitHub API 请求失败:`, error.message);
        continue;
      }
    }

    // 如果所有API请求都失败，使用默认值
    console.warn('无法获取默认分支，使用 "main" 作为后备');
    return "main";
  }

  // 单独的方法：测试所有镜像源的可用性
  static async testAllSources(owner, repo, ref) {
    const results = [];

    for (const source of this.MIRROR_SOURCES) {
      try {
        const url = source.url(owner, repo, ref);
        const startTime = Date.now();
        const response = await this.fetchWithTimeout(url, 5000);
        const responseTime = Date.now() - startTime;

        results.push({
          name: source.name,
          url,
          status: response.status,
          ok: response.ok,
          responseTime: `${responseTime}ms`,
          success: response.ok
        });
      } catch (error) {
        results.push({
          name: source.name,
          url: source.url(owner, repo, ref),
          status: 'ERROR',
          ok: false,
          responseTime: 'N/A',
          success: false,
          error: error.message
        });
      }
    }

    return results;
  }
}

// 使用示例
// GithubPackageFetcher.getPackageJson("https://github.com/facebook/react")
//   .then((pkg) => console.log(pkg))
//   .catch((err) => console.error(err));

// 测试镜像源可用性
// GithubPackageFetcher.testAllSources('facebook', 'react', 'main')
//   .then(results => console.table(results));